home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / msdos / blit.c < prev    next >
C/C++ Source or Header  |  2000-04-08  |  31KB  |  1,000 lines

  1. #include "mamalleg.h"
  2. #include "driver.h"
  3. #include <sys/farptr.h>
  4. #include <go32.h>
  5. #include "dirty.h"
  6. /* for VGA triple buffer - we need the register structure */
  7. #include "gen15khz.h"
  8.  
  9.  
  10. /* from video.c (required for 15.75KHz Arcade Monitor Modes) */
  11. extern int half_yres;
  12. extern int unchained;
  13.  
  14. extern char *dirty_old;
  15. extern char *dirty_new;
  16.  
  17. extern struct osd_bitmap *scrbitmap;
  18. extern int gfx_xoffset;
  19. extern int gfx_yoffset;
  20. extern int gfx_display_lines;
  21. extern int gfx_display_columns;
  22. extern int gfx_width;
  23. extern int gfx_height;
  24. extern int skiplines;
  25. extern int skipcolumns;
  26. extern int use_triplebuf;
  27. extern int triplebuf_pos,triplebuf_page_width;
  28. extern int mmxlfb;
  29.  
  30. unsigned int doublepixel[256];
  31. unsigned int quadpixel[256]; /* for quadring pixels */
  32.  
  33. UINT32 *palette_16bit_lookup;
  34.  
  35.  
  36. /* current 'page' for unchained modes */
  37. static int xpage = -1;
  38. /*default page sizes for non-triple buffering */
  39. int xpage_size = 0x8000;
  40. int no_xpages = 2;
  41.  
  42. /* this function lifted from Allegro */
  43. static int vesa_scroll_async(int x, int y)
  44. {
  45.    int ret;
  46.     #define BYTES_PER_PIXEL(bpp)     (((int)(bpp) + 7) / 8)    /* in Allegro */
  47.     extern __dpmi_regs _dpmi_reg;    /* in Allegro... I think */
  48.  
  49. //   vesa_xscroll = x;
  50. //   vesa_yscroll = y;
  51.  
  52. #if 0
  53.    int seg;
  54.    long a;
  55.     extern void (*_pm_vesa_scroller)(void);    /* in Allegro */
  56.     extern int _mmio_segment;    /* in Allegro */
  57.    if (_pm_vesa_scroller) {            /* use protected mode interface? */
  58.       seg = _mmio_segment ? _mmio_segment : _my_ds();
  59.  
  60.       a = ((x * BYTES_PER_PIXEL(screen->vtable->color_depth)) +
  61.        (y * ((unsigned long)screen->line[1] - (unsigned long)screen->line[0]))) / 4;
  62.  
  63.       asm (
  64.      "  pushw %%es ; "
  65.      "  movw %w1, %%es ; "         /* set the IO segment */
  66.      "  call *%0 ; "               /* call the VESA function */
  67.      "  popw %%es "
  68.  
  69.       :                                /* no outputs */
  70.  
  71.       : "S" (_pm_vesa_scroller),       /* function pointer in esi */
  72.     "a" (seg),                     /* IO segment in eax */
  73.     "b" (0x00),                    /* mode in ebx */
  74.     "c" (a & 0xFFFF),              /* low word of address in ecx */
  75.     "d" (a >> 16)                  /* high word of address in edx */
  76.  
  77. //      : "memory", "%edi", "%cc"        /* clobbers edi and flags */
  78.         : "memory", "%ebp", "%edi", "%cc" /* clobbers ebp, edi and flags (at least) */
  79.       );
  80.  
  81.       ret = 0;
  82.    }
  83.    else
  84. #endif
  85.    {                              /* use a real mode interrupt call */
  86.       _dpmi_reg.x.ax = 0x4F07;
  87.       _dpmi_reg.x.bx = 0;
  88.       _dpmi_reg.x.cx = x;
  89.       _dpmi_reg.x.dx = y;
  90.  
  91.       __dpmi_int(0x10, &_dpmi_reg);
  92.       ret = _dpmi_reg.h.ah;
  93.  
  94. //      _vsync_in();
  95.    }
  96.  
  97.    return (ret ? -1 : 0);
  98. }
  99.  
  100.  
  101. void blitscreen_dirty1_vga(void)
  102. {
  103.     int width4, x, y;
  104.     unsigned long *lb, address;
  105.  
  106.     width4 = (scrbitmap->line[1] - scrbitmap->line[0]) / 4;
  107.     address = 0xa0000 + gfx_xoffset + gfx_yoffset * gfx_width;
  108.     lb = (unsigned long *)(scrbitmap->line[skiplines] + skipcolumns);
  109.  
  110.     for (y = 0; y < gfx_display_lines; y += 16)
  111.     {
  112.         for (x = 0; x < gfx_display_columns; )
  113.         {
  114.             int w = 16;
  115.             if (ISDIRTY(x,y))
  116.             {
  117.                 unsigned long *lb0 = lb + x / 4;
  118.                 unsigned long address0 = address + x;
  119.                 int h;
  120.                 while (x + w < gfx_display_columns && ISDIRTY(x+w,y))
  121.                     w += 16;
  122.                 if (x + w > gfx_display_columns)
  123.                     w = gfx_display_columns - x;
  124.                 for (h = 0; h < 16 && y + h < gfx_display_lines; h++)
  125.                 {
  126.                     _dosmemputl(lb0, w/4, address0);
  127.                     lb0 += width4;
  128.                     address0 += gfx_width;
  129.                 }
  130.             }
  131.             x += w;
  132.         }
  133.         lb += 16 * width4;
  134.         address += 16 * gfx_width;
  135.     }
  136. }
  137.  
  138. void blitscreen_dirty0_vga(void)
  139. {
  140.     int width4,y,columns4;
  141.     unsigned long *lb, address;
  142.  
  143.     width4 = (scrbitmap->line[1] - scrbitmap->line[0]) / 4;
  144.     columns4 = gfx_display_columns/4;
  145.     address = 0xa0000 + gfx_xoffset + gfx_yoffset * gfx_width;
  146.     lb = (unsigned long *)(scrbitmap->line[skiplines] + skipcolumns);
  147.     for (y = 0; y < gfx_display_lines; y++)
  148.     {
  149.         _dosmemputl(lb,columns4,address);
  150.         lb+=width4;
  151.         address+=gfx_width;
  152.     }
  153. }
  154.  
  155. /* for flipping between the unchained VGA pages */
  156. INLINE void unchained_flip(void)
  157. {
  158.     int    flip_value1,flip_value2;
  159.     int    temp;
  160.  
  161. /* memory address of non-visible page */
  162.     temp = xpage_size * xpage;
  163.  
  164.     flip_value1 = ((temp & 0xff00) | 0x0c);
  165.     flip_value2 = (((temp << 8) & 0xff00) | 0x0d);
  166.  
  167. /* flip the page var */
  168.     xpage ++;
  169.     if (xpage == no_xpages)
  170.         xpage = 0;
  171. /* need to change the offset address during the active display interval */
  172. /* as the value is read during the vertical retrace */
  173.     __asm__ __volatile__ (
  174.  
  175.     "movw   $0x3da,%%dx \n"
  176.     "cli \n"
  177.     ".align 4                \n"
  178. /* check for active display interval */
  179.     "0:\n"
  180.     "inb    %%dx,%%al \n"
  181.     "testb  $1,%%al \n"
  182.     "jz      0b \n"
  183. /* change the offset address */
  184.     "movw   $0x3d4,%%dx \n"
  185.     "movw   %%cx,%%ax \n"
  186.     "outw   %%ax,%%dx \n"
  187.     "movw   %%bx,%%ax \n"
  188.     "outw   %%ax,%%dx \n"
  189.     "sti \n"
  190.  
  191.  
  192. /* outputs  (none)*/
  193.     :"=c" (flip_value1),
  194.     "=b" (flip_value2)
  195. /* inputs -
  196.  ecx = flip_value1 , ebx = flip_value2 */
  197.     :"0" (flip_value1),
  198.     "1" (flip_value2)
  199. /* registers modified */
  200.     :"ax", "dx", "cc", "memory"
  201.     );
  202. }
  203.  
  204.  
  205.  
  206. /* unchained dirty modes */
  207. void blitscreen_dirty1_unchained_vga(void)
  208. {
  209.     int x, y, i, outval, dirty_page, triple_page, write_triple;
  210.     int plane, planeval, iloop, page;
  211.     unsigned long *lb, address, triple_address;
  212.     unsigned char *lbsave;
  213.     unsigned long asave, triple_save;
  214.     static int width4, word_blit, dirty_height;
  215.     static int source_width, source_line_width, dest_width, dest_line_width;
  216.  
  217.     /* calculate our statics on the first call */
  218.     if (xpage == -1)
  219.     {
  220.         width4 = ((scrbitmap->line[1] - scrbitmap->line[0]) >> 2);
  221.         source_width = width4 << half_yres;
  222.         dest_width = gfx_width >> 2;
  223.         dest_line_width = (gfx_width << 2) >> half_yres;
  224.         source_line_width = width4 << 4;
  225.         xpage = 1;
  226.         dirty_height = 16 >> half_yres;
  227.         /* check if we have to do word rather than double word updates */
  228.         word_blit = ((gfx_display_columns >> 2) & 3);
  229.     }
  230.  
  231.     /* setup or selector */
  232.     _farsetsel(screen->seg);
  233.  
  234.     dirty_page = xpage;
  235.     /* non visible page, if we're triple buffering */
  236.     triple_page = xpage + 1;
  237.     if (triple_page == no_xpages)
  238.         triple_page = 0;
  239.  
  240.     /* need to update all 'pages', but only update each page while it isn't visible */
  241.     for (page = 0; page < 2; page ++)
  242.     {
  243.         planeval=0x0100;
  244.         write_triple = (!page | (no_xpages == 3));
  245.  
  246.         /* go through each bit plane */
  247.         for (plane = 0; plane < 4 ;plane ++)
  248.         {
  249.             address = 0xa0000 + (xpage_size * dirty_page)+(gfx_xoffset >> 2) + (((gfx_yoffset >> half_yres) * gfx_width) >> 2);
  250.             triple_address = 0xa0000 + (xpage_size * triple_page)+(gfx_xoffset >> 2) + (((gfx_yoffset >> half_yres) * gfx_width) >> 2);
  251.             lb = (unsigned long *)(scrbitmap->line[skiplines] + skipcolumns + plane);
  252.             /*set the bit plane */
  253.             outportw(0x3c4, planeval|0x02);
  254.             for (y = 0; y < gfx_display_lines ; y += 16)
  255.             {
  256.                 for (x = 0; x < gfx_display_columns; )
  257.                 {
  258.                     int w = 16;
  259.                     if (ISDIRTY(x,y))
  260.                     {
  261.                         unsigned long *lb0 = lb + (x >> 2);
  262.                         unsigned long address0 = address + (x >> 2);
  263.                         unsigned long address1 = triple_address + (x >> 2);
  264.                         int h;
  265.                         while (x + w < gfx_display_columns && ISDIRTY(x+w,y))
  266.                             w += 16;
  267.                         if (x + w > gfx_display_columns)
  268.                             w = gfx_display_columns - x;
  269.                         if(word_blit)
  270.                         {
  271.                             iloop = w >> 3;
  272.                             for (h = 0; h < dirty_height && (y + (h << half_yres)) < gfx_display_lines; h++)
  273.                             {
  274.                                 asave = address0;
  275.                                 triple_save = address1;
  276.                                 lbsave = (unsigned char *)lb0;
  277.                                 for(i = 0; i < iloop; i++)
  278.                                 {
  279.                                     outval = *lbsave | (lbsave[4] << 8);
  280.                                     _farnspokew(asave, outval);
  281.                                     /* write 2 pages on first pass if triple buffering */
  282.                                     if (write_triple)
  283.                                     {
  284.                                         _farnspokew(triple_save, outval);
  285.                                         triple_save += 2;
  286.                                     }
  287.                                     lbsave += 8;
  288.                                     asave += 2;
  289.                                 }
  290.                                 if (w&4)
  291.                                 {
  292.                                     _farnspokeb(asave, *lbsave);
  293.                                        if (write_triple)
  294.                                         _farnspokeb(triple_save, *lbsave);
  295.                                 }
  296.  
  297.  
  298.                                 lb0 += source_width;
  299.                                 address0 += dest_width;
  300.                                 address1 += dest_width;
  301.                             }
  302.                         }
  303.                         else
  304.                         {
  305.                             iloop = w >> 4;
  306.                             for (h = 0; h < dirty_height && (y + (h << half_yres)) < gfx_display_lines; h++)
  307.                             {
  308.                                 asave = address0;
  309.                                 triple_save = address1;
  310.                                 lbsave = (unsigned char *)lb0;
  311.                                 for(i = 0; i < iloop; i++)
  312.                                 {
  313.                                     outval = *lbsave | (lbsave[4] << 8) | (lbsave[8] << 16) | (lbsave[12] << 24);
  314.                                     _farnspokel(asave, outval);
  315.                                     /* write 2 pages on first pass if triple buffering */
  316.                                     if (page == 0 && no_xpages == 3)
  317.                                     {
  318.                                         _farnspokel(triple_save, outval);
  319.                                         triple_save += 4;
  320.                                     }
  321.                                     lbsave += 16;
  322.                                     asave += 4;
  323.                                 }
  324.                                 lb0 += source_width;
  325.                                 address0 += dest_width;
  326.                                 address1 += dest_width;
  327.                             }
  328.                         }
  329.                     }
  330.                     x += w;
  331.                 }
  332.                 lb += source_line_width;
  333.                 address += dest_line_width;
  334.                 triple_address += dest_line_width;
  335.             }
  336.             /* move onto the next bit plane */
  337.             planeval <<= 1;
  338.         }
  339.         /* 'bank switch' our unchained output on the first loop */
  340.         if(!page)
  341.             unchained_flip();
  342.         /* move onto next 'page' */
  343.         dirty_page += (no_xpages - 1);
  344.         if (dirty_page >= no_xpages)
  345.             dirty_page -= no_xpages;
  346.     }
  347. }
  348.  
  349. void init_unchained_blit(void)
  350. {
  351.     xpage=-1;
  352. }
  353.  
  354. /* Macros for non dirty unchained blits */
  355. #define UNCHAIN_BLIT_START \
  356.     int dummy1,dummy2,dummy3; \
  357.     __asm__ __volatile__ ( \
  358. /* save es and set it to our video selector */ \
  359.     "pushw  %%es \n" \
  360.     "movw   %%dx,%%es \n" \
  361.     "movw   $0x102,%%ax \n" \
  362.     "cld \n" \
  363.     ".align 4 \n" \
  364. /* --bit plane loop-- */ \
  365.     "0:\n" \
  366. /* save everything */ \
  367.     "pushl  %%ebx \n" \
  368.     "pushl  %%edi \n" \
  369.     "pushl  %%eax \n" \
  370.     "pushl  %%ecx \n" \
  371. /* set the bit plane */ \
  372.     "movw   $0x3c4,%%dx \n" \
  373.     "outw   %%ax,%%dx \n" \
  374. /* edx now free, so use it for the memwidth */ \
  375.     "movl   %4,%%edx \n" \
  376. /* --height loop-- */ \
  377.     "1:\n" \
  378. /* save counter , source + dest address */ \
  379.     "pushl     %%ecx \n" \
  380.     "pushl    %%ebx \n" \
  381.     "pushl    %%edi \n" \
  382. /* --width loop-- */ \
  383.     "movl   %3,%%ecx \n" \
  384.     "2:\n" \
  385. /* get the 4 bytes */ \
  386. /* bswap should be faster than shift, */ \
  387. /* movl should be faster then movb */ \
  388.     "movl   %%ds:12(%%ebx),%%eax \n" \
  389.     "movb   %%ds:8(%%ebx),%%ah \n" \
  390.     "bswap  %%eax \n" \
  391.     "movb   %%ds:(%%ebx),%%al \n" \
  392.     "movb   %%ds:4(%%ebx),%%ah \n" \
  393. /* write the thing to video */ \
  394.     "stosl \n" \
  395. /* move onto next source address */ \
  396.     "addl   $16,%%ebx \n" \
  397.     "loop    2b \n"
  398.  
  399. #define UNCHAIN_BLIT_END \
  400. /* --end of width loop-- */ \
  401. /* get counter, source + dest address back */ \
  402.     "popl    %%edi \n" \
  403.     "popl    %%ebx \n" \
  404.     "popl   %%ecx \n" \
  405. /* move to the next line */ \
  406.     "addl   %%edx,%%ebx \n" \
  407.     "addl   %%esi,%%edi \n" \
  408.     "loop   1b \n" \
  409. /* --end of height loop-- */ \
  410. /* get everything back */ \
  411.     "popl   %%ecx \n" \
  412.     "popl   %%eax \n"  \
  413.     "popl   %%edi \n" \
  414.     "popl   %%ebx \n" \
  415. /* move onto next bit plane */ \
  416.     "incl   %%ebx \n" \
  417.     "shlb   $1,%%ah \n" \
  418. /* check if we've done all 4 or not */ \
  419.     "testb  $0x10,%%ah \n" \
  420.     "jz        0b \n" \
  421. /* --end of bit plane loop-- */ \
  422. /* restore es */ \
  423.     "popw   %%es \n" \
  424. /* outputs (aka clobbered input) */ \
  425.     :"=S" (dummy1), \
  426.     "=b" (dummy2), \
  427.     "=d" (dummy3) \
  428. /* inputs */ \
  429. /* %0=width, %1=memwidth, */ \
  430. /* esi = scrwidth */ \
  431. /* ebx = src, ecx = height */ \
  432. /* edx = seg, edi = address */ \
  433.     :"g" (width), \
  434.     "g" (memwidth), \
  435.     "c" (height), \
  436.     "D" (address), \
  437.     "0" (scrwidth), \
  438.     "1" (src), \
  439.     "2" (seg) \
  440. /* registers modified */ \
  441.     :"ax", "cc", "memory" \
  442.     );
  443.  
  444.  
  445.  
  446. /*asm routine for unchained blit - writes 4 bytes at a time */
  447. INLINE void unchain_dword_blit(unsigned long *src,short seg,unsigned long address,int width,int height,int memwidth,int scrwidth)
  448. {
  449. /* straight forward double word blit */
  450.     UNCHAIN_BLIT_START
  451.     UNCHAIN_BLIT_END
  452. }
  453.  
  454. /*asm routine for unchained blit - writes 4 bytes at a time, then 2 'odd' bytes at the end of each row */
  455. INLINE void unchain_word_blit(unsigned long *src,short seg,unsigned long address,int width,int height,int memwidth,int scrwidth)
  456. {
  457.     UNCHAIN_BLIT_START
  458. /* get the extra 2 bytes at end of the row */
  459.     "movl   %%ds:(%%ebx),%%eax \n"
  460.     "movb   %%ds:4(%%ebx),%%ah \n"
  461. /* write the thing to video */
  462.     "stosw \n"
  463.     UNCHAIN_BLIT_END
  464. }
  465.  
  466. /*asm routine for unchained blit - writes 4 bytes at a time, then 1 'odd' byte at the end of each row */
  467. INLINE void unchain_byte_blit(unsigned long *src,short seg,unsigned long address,int width,int height,int memwidth,int scrwidth)
  468. {
  469.     UNCHAIN_BLIT_START
  470. /* get the extra byte at end of the row */
  471.     "movb   %%ds:(%%ebx),%%al \n"
  472. /* write the thing to video */
  473.     "stosb \n"
  474.     UNCHAIN_BLIT_END
  475. }
  476.  
  477. /* unchained 'non-dirty' modes */
  478. void blitscreen_dirty0_unchained_vga(void)
  479. {
  480.     unsigned long *lb, address;
  481.     static int width4,columns4,column_chained,memwidth,scrwidth,disp_height,blit_type;
  482.  
  483.    /* only calculate our statics the first time around */
  484.     if(xpage==-1)
  485.     {
  486.         width4 = (scrbitmap->line[1] - scrbitmap->line[0]) >> 2;
  487.         columns4 = gfx_display_columns >> 2;
  488.         disp_height = gfx_display_lines >> half_yres;
  489.  
  490.         xpage = 1;
  491.         memwidth = (scrbitmap->line[1] - scrbitmap->line[0]) << half_yres;
  492.         scrwidth = gfx_width >> 2;
  493.  
  494.         /* check for 'not divisible by 8' */
  495.         if((columns4 & 1))
  496.             blit_type = 2;    /* byte blit */
  497.         else
  498.         {
  499.             if((columns4 & 2))
  500.                 blit_type = 1; /* word blit */
  501.             else
  502.                 blit_type = 0; /* double word blit */
  503.         }
  504.  
  505.         column_chained = columns4 >> 2;
  506.     }
  507.  
  508.     /* get the start of the screen bitmap */
  509.     lb = (unsigned long *)(scrbitmap->line[skiplines] + skipcolumns);
  510.     /* and the start address in video memory */
  511.     address = 0xa0000 + (xpage_size * xpage)+(gfx_xoffset >> 2) + (((gfx_yoffset >> half_yres) * gfx_width) >> 2);
  512.     /* call the appropriate blit routine */
  513.     switch (blit_type)
  514.     {
  515.         case 0: /* double word blit */
  516.             unchain_dword_blit (lb, screen->seg, address, column_chained, disp_height, memwidth, scrwidth);
  517.             break;
  518.         case 1: /* word blit */
  519.             unchain_word_blit (lb, screen->seg, address, column_chained, disp_height, memwidth, scrwidth);
  520.             break;
  521.         case 2: /* byte blit */
  522.             unchain_byte_blit (lb, screen->seg, address, column_chained, disp_height, memwidth, scrwidth);
  523.             break;
  524.     }
  525.     /* 'bank switch' our unchained output */
  526.     unchained_flip();
  527. }
  528.  
  529.  
  530.  
  531. /* setup register array to be unchained */
  532. void unchain_vga(Register *pReg)
  533. {
  534. /* setup registers for an unchained mode */
  535.     pReg[UNDERLINE_LOC_INDEX].value = 0x00;
  536.     pReg[MODE_CONTROL_INDEX].value = 0xe3;
  537.     pReg[MEMORY_MODE_INDEX].value = 0x06;
  538. /* flag the fact it's unchained */
  539.     unchained = 1;
  540. }
  541.  
  542. INLINE void copyline_1x_8bpp(unsigned char *src,short seg,unsigned long address,int width4)
  543. {
  544.     short src_seg;
  545.  
  546.     src_seg = _my_ds();
  547.  
  548.     _movedatal(src_seg,(unsigned long)src,seg,address,width4);
  549. }
  550.  
  551. INLINE void copyline_1x_16bpp(unsigned char *src,short seg,unsigned long address,int width2)
  552. {
  553.     short src_seg;
  554.  
  555.     src_seg = _my_ds();
  556.  
  557.     _movedatal(src_seg,(unsigned long)src,seg,address,width2);
  558. }
  559.  
  560. #if 1 /* use the C approach instead */
  561. INLINE void copyline_2x_8bpp(unsigned char *src,short seg,unsigned long address,int width4)
  562. {
  563.     __asm__ __volatile__ (
  564.     "pushw %%es              \n"
  565.     "movw %%dx, %%es         \n"
  566.     "cld                     \n"
  567.     ".align 4                \n"
  568.     "0:                      \n"
  569.     "lodsl                   \n"
  570.     "movl %%eax, %%ebx       \n"
  571.     "bswap %%eax             \n"
  572.     "xchgw %%ax,%%bx         \n"
  573.     "roll $8, %%eax          \n"
  574.     "stosl                   \n"
  575.     "movl %%ebx, %%eax       \n"
  576.     "rorl $8, %%eax          \n"
  577.     "stosl                   \n"
  578.     "loop 0b                 \n"
  579.     "popw %%ax               \n"
  580.     "movw %%ax, %%es         \n"
  581.     :
  582.     "=c" (width4),
  583.     "=d" (seg),
  584.     "=S" (src),
  585.     "=D" (address)
  586.     :
  587.     "0" (width4),
  588.     "1" (seg),
  589.     "2" (src),
  590.     "3" (address):
  591.     "ax", "bx", "cc", "memory");
  592. }
  593. #else
  594. INLINE void copyline_2x_8bpp(unsigned char *src,short seg,unsigned long address,int width4)
  595. {
  596.     int i;
  597.  
  598.     /* set up selector */
  599.     _farsetsel(seg);
  600.  
  601.     for (i = width; i > 0; i--)
  602.     {
  603.         _farnspokel (address, doublepixel[*src] | (doublepixel[*(src+1)] << 16));
  604.         _farnspokel (address+4, doublepixel[*(src+2)] | (doublepixel[*(src+3)] << 16));
  605.         address+=8;
  606.         src+=4;
  607.     }
  608. }
  609. #endif
  610.  
  611. INLINE void copyline_2x_16bpp(unsigned char *src,short seg,unsigned long address,int width2)
  612. {
  613.     __asm__ __volatile__ (
  614.     "pushw %%es              \n"
  615.     "movw %%dx, %%es         \n"
  616.     "cld                     \n"
  617.     ".align 4                \n"
  618.     "0:                      \n"
  619.     "lodsl                   \n"
  620.     "movl %%eax, %%ebx       \n"
  621.     "roll $16, %%eax         \n"
  622.     "xchgw %%ax,%%bx         \n"
  623.     "stosl                   \n"
  624.     "movl %%ebx, %%eax       \n"
  625.     "stosl                   \n"
  626.     "loop 0b                 \n"
  627.     "popw %%ax               \n"
  628.     "movw %%ax, %%es         \n"
  629.     :
  630.     "=c" (width2),
  631.     "=d" (seg),
  632.     "=S" (src),
  633.     "=D" (address)
  634.     :
  635.     "0" (width2),
  636.     "1" (seg),
  637.     "2" (src),
  638.     "3" (address):
  639.     "ax", "bx", "cc", "memory");
  640. }
  641.  
  642. INLINE void copyline_3x_16bpp(unsigned char *src,short seg,unsigned long address,int width2)
  643. {
  644.     __asm__ __volatile__ (
  645.     "pushw %%es              \n"
  646.     "movw %%dx, %%es         \n"
  647.     "cld                     \n"
  648.     ".align 4                \n"
  649.     "0:                      \n"
  650.     "lodsl                   \n"
  651.     "movl %%eax, %%ebx       \n"
  652.     "roll $16, %%eax         \n"
  653.     "xchgw %%ax,%%bx         \n"
  654.     "stosl                   \n"
  655.     "stosw                   \n"
  656.     "movl %%ebx, %%eax       \n"
  657.     "stosl                   \n"
  658.     "stosw                   \n"
  659.     "loop 0b                 \n"
  660.     "popw %%ax               \n"
  661.     "movw %%ax, %%es         \n"
  662.     :
  663.     "=c" (width2),
  664.     "=d" (seg),
  665.     "=S" (src),
  666.     "=D" (address)
  667.     :
  668.     "0" (width2),
  669.     "1" (seg),
  670.     "2" (src),
  671.     "3" (address):
  672.     "ax", "bx", "cc", "memory");
  673. }
  674.  
  675. INLINE void copyline_4x_16bpp(unsigned char *src,short seg,unsigned long address,int width2)
  676. {
  677.     __asm__ __volatile__ (
  678.     "pushw %%es              \n"
  679.     "movw %%dx, %%es         \n"
  680.     "cld                     \n"
  681.     ".align 4                \n"
  682.     "0:                      \n"
  683.     "lodsl                   \n"
  684.     "movl %%eax, %%ebx       \n"
  685.     "roll $16, %%eax         \n"
  686.     "xchgw %%ax,%%bx         \n"
  687.     "stosl                   \n"
  688.     "stosl                   \n"
  689.     "movl %%ebx, %%eax       \n"
  690.     "stosl                   \n"
  691.     "stosl                      \n"
  692.  
  693.  
  694.     "loop 0b                 \n"
  695.     "popw %%ax               \n"
  696.     "movw %%ax, %%es         \n"
  697.     :
  698.     "=c" (width2),
  699.     "=d" (seg),
  700.     "=S" (src),
  701.     "=D" (address)
  702.     :
  703.     "0" (width2),
  704.     "1" (seg),
  705.     "2" (src),
  706.     "3" (address):
  707.     "ax", "bx", "cc", "memory");
  708. }
  709.  
  710. INLINE void copyline_3x_8bpp(unsigned char *src,short seg,unsigned long address,int width4)
  711. {
  712.     int i;
  713.  
  714.     /* set up selector */
  715.     _farsetsel(seg);
  716.  
  717.     for (i = width4; i > 0; i--)
  718.     {
  719.         _farnspokel (address, (quadpixel[*src] & 0x00ffffff) | (quadpixel[*(src+1)] & 0xff000000));
  720.         _farnspokel (address+4, (quadpixel[*(src+1)] & 0x0000ffff) | (quadpixel[*(src+2)] & 0xffff0000));
  721.         _farnspokel (address+8, (quadpixel[*(src+2)] & 0x000000ff) | (quadpixel[*(src+3)] & 0xffffff00));
  722.         address+=3*4;
  723.         src+=4;
  724.     }
  725. }
  726.  
  727. INLINE void copyline_4x_8bpp(unsigned char *src,short seg,unsigned long address,int width4)
  728. {
  729.     int i;
  730.  
  731.     /* set up selector */
  732.     _farsetsel(seg);
  733.  
  734.     for (i = width4; i > 0; i--)
  735.     {
  736.         _farnspokel (address, quadpixel[*src]);
  737.         _farnspokel (address+4, quadpixel[*(src+1)]);
  738.         _farnspokel (address+8, quadpixel[*(src+2)]);
  739.         _farnspokel (address+12, quadpixel[*(src+3)]);
  740.         address+=16;
  741.         src+=4;
  742.     }
  743. }
  744.  
  745.  
  746.  
  747.  
  748. INLINE void copyline_1x_16bpp_palettized(unsigned char *src,short seg,unsigned long address,int width2)
  749. {
  750.     int i;
  751.     unsigned short *s=(unsigned short *)src;
  752.  
  753.     /* set up selector */
  754.     _farsetsel(seg);
  755.  
  756.     for (i = width2; i > 0; i--)
  757.     {
  758.         UINT32 d1,d2;
  759.  
  760.         d1 = palette_16bit_lookup[*(s++)];
  761.         d2 = palette_16bit_lookup[*(s++)];
  762.         _farnspokel(address,(d1 & 0x0000ffff) | (d2 & 0xffff0000));
  763.         address+=4;
  764.     }
  765. }
  766.  
  767. INLINE void copyline_2x_16bpp_palettized(unsigned char *src,short seg,unsigned long address,int width2)
  768. {
  769.     int i;
  770.     unsigned short *s=(unsigned short *)src;
  771.  
  772.     /* set up selector */
  773.     _farsetsel(seg);
  774.  
  775.     for (i = 2*width2; i > 0; i--)
  776.     {
  777.         _farnspokel(address,palette_16bit_lookup[*(s++)]);
  778.         address+=4;
  779.     }
  780. }
  781.  
  782. INLINE void copyline_3x_16bpp_palettized(unsigned char *src,short seg,unsigned long address,int width2)
  783. {
  784.     int i;
  785.     unsigned short *s=(unsigned short *)src;
  786.  
  787.     /* set up selector */
  788.     _farsetsel(seg);
  789.  
  790.     for (i = width2; i > 0; i--)
  791.     {
  792.         UINT32 d1,d2;
  793.  
  794.         d1 = palette_16bit_lookup[*(s++)];
  795.         d2 = palette_16bit_lookup[*(s++)];
  796.         _farnspokel(address,d1);
  797.         _farnspokel(address+4,(d1 & 0x0000ffff) | (d2 & 0xffff0000));
  798.         _farnspokel(address+8,d2);
  799.         address+=3*4;
  800.     }
  801. }
  802.  
  803. INLINE void copyline_4x_16bpp_palettized(unsigned char *src,short seg,unsigned long address,int width2)
  804. {
  805.     int i;
  806.     unsigned short *s=(unsigned short *)src;
  807.  
  808.     /* set up selector */
  809.     _farsetsel(seg);
  810.  
  811.     for (i = 2*width2; i > 0; i--)
  812.     {
  813.         UINT32 d;
  814.  
  815.         d = palette_16bit_lookup[*(s++)];
  816.         _farnspokel(address,d);
  817.         _farnspokel(address+4,d);
  818.         address+=8;
  819.     }
  820. }
  821.  
  822.  
  823.  
  824.  
  825. #define DIRTY1(MX,MY,SL,BPP,PALETTIZED) \
  826.     short dest_seg; \
  827.     int x,y,vesa_line,line_offs,xoffs; \
  828.     unsigned char *lb; \
  829.     unsigned long address; \
  830.     dest_seg = screen->seg; \
  831.     vesa_line = gfx_yoffset; \
  832.     line_offs = scrbitmap->line[1] - scrbitmap->line[0]; \
  833.     xoffs = (BPP/8)*gfx_xoffset; \
  834.     lb = scrbitmap->line[skiplines] + (BPP/8)*skipcolumns; \
  835.     for (y = 0;y < gfx_display_lines;y += 16) \
  836.     { \
  837.         for (x = 0;x < gfx_display_columns; /* */) \
  838.         { \
  839.             int w = 16; \
  840.             if (ISDIRTY(x,y)) \
  841.             { \
  842.                 unsigned char *src = lb + (BPP/8)*x; \
  843.                 int vesa_line0 = vesa_line, h; \
  844.                 while (x + w < gfx_display_columns && ISDIRTY(x+w,y)) \
  845.                     w += 16; \
  846.                 if (x + w > gfx_display_columns) \
  847.                     w = gfx_display_columns - x; \
  848.                 for (h = 0; h < 16 && y + h < gfx_display_lines; h++) \
  849.                 { \
  850.                     address = bmp_write_line(screen,vesa_line0) + xoffs + MX*(BPP/8)*x; \
  851.                     copyline_##MX##x_##BPP##bpp##PALETTIZED(src,dest_seg,address,w/(4/(BPP/8))); \
  852.                     if ((MY > 2) || ((MY == 2) && (SL == 0))) { \
  853.                         address = bmp_write_line(screen,vesa_line0+1) + xoffs + MX*(BPP/8)*x; \
  854.                         copyline_##MX##x_##BPP##bpp##PALETTIZED(src,dest_seg,address,w/(4/(BPP/8))); \
  855.                     } \
  856.                     if ((MY > 3) || ((MY == 3) && (SL == 0))) { \
  857.                         address = bmp_write_line(screen,vesa_line0+2) + xoffs + MX*(BPP/8)*x; \
  858.                         copyline_##MX##x_##BPP##bpp##PALETTIZED(src,dest_seg,address,w/(4/(BPP/8))); \
  859.                     } \
  860.                     vesa_line0 += MY; \
  861.                     src += line_offs; \
  862.                 } \
  863.             } \
  864.             x += w; \
  865.         } \
  866.         vesa_line += MY*16; \
  867.         lb += 16 * line_offs; \
  868.     }
  869.  
  870. #define DIRTY0(MX,MY,SL,BPP,PALETTIZED) \
  871.     short dest_seg; \
  872.     int y,vesa_line,line_offs,xoffs,width; \
  873.     unsigned char *src; \
  874.     unsigned long address, address_offset; \
  875.     dest_seg = screen->seg; \
  876.     vesa_line = gfx_yoffset; \
  877.     line_offs = (scrbitmap->line[1] - scrbitmap->line[0]); \
  878.     xoffs = (BPP/8)*(gfx_xoffset + triplebuf_pos); \
  879.     width = gfx_display_columns/(4/(BPP/8)); \
  880.     src = scrbitmap->line[skiplines] + (BPP/8)*skipcolumns;    \
  881.     if (mmxlfb) { \
  882.         address = bmp_write_line(screen, vesa_line); \
  883.         _farsetsel (screen->seg); \
  884.         address_offset = bmp_write_line(screen, vesa_line+1) - address; \
  885.         address += xoffs; \
  886.         { \
  887.         extern void asmblit_##MX##x_##MY##y_##SL##sl_##BPP##bpp##PALETTIZED \
  888.             (int, int, unsigned char *, int, unsigned long, unsigned long); \
  889.         asmblit_##MX##x_##MY##y_##SL##sl_##BPP##bpp##PALETTIZED \
  890.             (width, gfx_display_lines, src, line_offs, address, address_offset); \
  891.         } \
  892.     } \
  893.     else { \
  894.         for (y = 0;y < gfx_display_lines;y++) \
  895.         { \
  896.             address = bmp_write_line(screen,vesa_line) + xoffs; \
  897.             copyline_##MX##x_##BPP##bpp##PALETTIZED(src,dest_seg,address,width); \
  898.             if ((MY > 2) || ((MY == 2) && (SL == 0))) { \
  899.                 address = bmp_write_line(screen,vesa_line+1) + xoffs; \
  900.                 copyline_##MX##x_##BPP##bpp##PALETTIZED(src,dest_seg,address,width); \
  901.             } \
  902.             if ((MY > 3) || ((MY == 3) && (SL == 0))) { \
  903.                 address = bmp_write_line(screen,vesa_line+2) + xoffs; \
  904.                 copyline_##MX##x_##BPP##bpp##PALETTIZED(src,dest_seg,address,width); \
  905.             } \
  906.             vesa_line += MY; \
  907.             src += line_offs; \
  908.         } \
  909.     } \
  910.     if (use_triplebuf) \
  911.     { \
  912.         vesa_scroll_async(triplebuf_pos,0); \
  913.         triplebuf_pos = (triplebuf_pos + triplebuf_page_width) % (3*triplebuf_page_width); \
  914.     }
  915.  
  916.  
  917. void blitscreen_dirty1_vesa_1x_1x_8bpp(void)   { DIRTY1(1,1,0,8,)  }
  918. void blitscreen_dirty1_vesa_1x_2x_8bpp(void)   { DIRTY1(1,2,0,8,)  }
  919. void blitscreen_dirty1_vesa_1x_2xs_8bpp(void)  { DIRTY1(1,2,1,8,)  }
  920. void blitscreen_dirty1_vesa_2x_1x_8bpp(void)   { DIRTY1(2,1,0,8,)  }
  921. void blitscreen_dirty1_vesa_3x_1x_8bpp(void)   { DIRTY1(3,1,0,8,)  }
  922. void blitscreen_dirty1_vesa_2x_2x_8bpp(void)   { DIRTY1(2,2,0,8,)  }
  923. void blitscreen_dirty1_vesa_2x_2xs_8bpp(void)  { DIRTY1(2,2,1,8,)  }
  924. void blitscreen_dirty1_vesa_2x_3x_8bpp(void)   { DIRTY1(2,3,0,8,)  }
  925. void blitscreen_dirty1_vesa_2x_3xs_8bpp(void)  { DIRTY1(2,3,1,8,)  }
  926. void blitscreen_dirty1_vesa_3x_2x_8bpp(void)   { DIRTY1(3,2,0,8,)  }
  927. void blitscreen_dirty1_vesa_3x_2xs_8bpp(void)  { DIRTY1(3,2,1,8,)  }
  928. void blitscreen_dirty1_vesa_3x_3x_8bpp(void)   { DIRTY1(3,3,0,8,)  }
  929. void blitscreen_dirty1_vesa_3x_3xs_8bpp(void)  { DIRTY1(3,3,1,8,)  }
  930. void blitscreen_dirty1_vesa_4x_2x_8bpp(void)   { DIRTY1(4,2,0,8,)  }
  931. void blitscreen_dirty1_vesa_4x_2xs_8bpp(void)  { DIRTY1(4,2,1,8,)  }
  932. void blitscreen_dirty1_vesa_4x_3x_8bpp(void)   { DIRTY1(4,3,0,8,)  }
  933. void blitscreen_dirty1_vesa_4x_3xs_8bpp(void)  { DIRTY1(4,3,1,8,)  }
  934.  
  935. void blitscreen_dirty1_vesa_1x_1x_16bpp(void)  { DIRTY1(1,1,0,16,) }
  936. void blitscreen_dirty1_vesa_1x_2x_16bpp(void)  { DIRTY1(1,2,0,16,) }
  937. void blitscreen_dirty1_vesa_1x_2xs_16bpp(void) { DIRTY1(1,2,1,16,) }
  938. void blitscreen_dirty1_vesa_2x_1x_16bpp(void)  { DIRTY1(2,1,0,16,) }
  939. void blitscreen_dirty1_vesa_2x_2x_16bpp(void)  { DIRTY1(2,2,0,16,) }
  940. void blitscreen_dirty1_vesa_2x_2xs_16bpp(void) { DIRTY1(2,2,1,16,) }
  941. void blitscreen_dirty1_vesa_3x_1x_16bpp(void)  { DIRTY1(3,1,0,16,) }
  942. void blitscreen_dirty1_vesa_3x_2x_16bpp(void)  { DIRTY1(3,2,0,16,) }
  943. void blitscreen_dirty1_vesa_3x_2xs_16bpp(void) { DIRTY1(3,2,1,16,) }
  944. void blitscreen_dirty1_vesa_4x_2x_16bpp(void)  { DIRTY1(4,2,0,16,) }
  945. void blitscreen_dirty1_vesa_4x_2xs_16bpp(void) { DIRTY1(4,2,1,16,) }
  946.  
  947. void blitscreen_dirty1_vesa_1x_1x_16bpp_palettized(void)  { DIRTY1(1,1,0,16,_palettized) }
  948. void blitscreen_dirty1_vesa_1x_2x_16bpp_palettized(void)  { DIRTY1(1,2,0,16,_palettized) }
  949. void blitscreen_dirty1_vesa_1x_2xs_16bpp_palettized(void) { DIRTY1(1,2,1,16,_palettized) }
  950. void blitscreen_dirty1_vesa_2x_1x_16bpp_palettized(void)  { DIRTY1(2,1,0,16,_palettized) }
  951. void blitscreen_dirty1_vesa_2x_2x_16bpp_palettized(void)  { DIRTY1(2,2,0,16,_palettized) }
  952. void blitscreen_dirty1_vesa_2x_2xs_16bpp_palettized(void) { DIRTY1(2,2,1,16,_palettized) }
  953. void blitscreen_dirty1_vesa_3x_1x_16bpp_palettized(void)  { DIRTY1(3,1,0,16,_palettized) }
  954. void blitscreen_dirty1_vesa_3x_2x_16bpp_palettized(void)  { DIRTY1(3,2,0,16,_palettized)  }
  955. void blitscreen_dirty1_vesa_3x_2xs_16bpp_palettized(void) { DIRTY1(3,2,1,16,_palettized) }
  956. void blitscreen_dirty1_vesa_4x_2x_16bpp_palettized(void)  { DIRTY1(4,2,0,16,_palettized) }
  957. void blitscreen_dirty1_vesa_4x_2xs_16bpp_palettized(void) { DIRTY1(4,2,1,16,_palettized) }
  958.  
  959. void blitscreen_dirty0_vesa_1x_1x_8bpp(void)   { DIRTY0(1,1,0,8,)  }
  960. void blitscreen_dirty0_vesa_1x_2x_8bpp(void)   { DIRTY0(1,2,0,8,)  }
  961. void blitscreen_dirty0_vesa_1x_2xs_8bpp(void)  { DIRTY0(1,2,1,8,)  }
  962. void blitscreen_dirty0_vesa_2x_1x_8bpp(void)   { DIRTY0(2,1,0,8,)  }
  963. void blitscreen_dirty0_vesa_3x_1x_8bpp(void)   { DIRTY0(3,1,0,8,)  }
  964. void blitscreen_dirty0_vesa_2x_2x_8bpp(void)   { DIRTY0(2,2,0,8,)  }
  965. void blitscreen_dirty0_vesa_2x_2xs_8bpp(void)  { DIRTY0(2,2,1,8,)  }
  966. void blitscreen_dirty0_vesa_2x_3x_8bpp(void)   { DIRTY0(2,3,0,8,)  }
  967. void blitscreen_dirty0_vesa_2x_3xs_8bpp(void)  { DIRTY0(2,3,1,8,)  }
  968. void blitscreen_dirty0_vesa_3x_2x_8bpp(void)   { DIRTY0(3,2,0,8,)  }
  969. void blitscreen_dirty0_vesa_3x_2xs_8bpp(void)  { DIRTY0(3,2,1,8,)  }
  970. void blitscreen_dirty0_vesa_3x_3x_8bpp(void)   { DIRTY0(3,3,0,8,)  }
  971. void blitscreen_dirty0_vesa_3x_3xs_8bpp(void)  { DIRTY0(3,3,1,8,)  }
  972. void blitscreen_dirty0_vesa_4x_2x_8bpp(void)   { DIRTY0(4,2,0,8,)  }
  973. void blitscreen_dirty0_vesa_4x_2xs_8bpp(void)  { DIRTY0(4,2,1,8,)  }
  974. void blitscreen_dirty0_vesa_4x_3x_8bpp(void)   { DIRTY0(4,3,0,8,)  }
  975. void blitscreen_dirty0_vesa_4x_3xs_8bpp(void)  { DIRTY0(4,3,1,8,)  }
  976.  
  977. void blitscreen_dirty0_vesa_1x_1x_16bpp(void)  { DIRTY0(1,1,0,16,) }
  978. void blitscreen_dirty0_vesa_1x_2x_16bpp(void)  { DIRTY0(1,2,0,16,) }
  979. void blitscreen_dirty0_vesa_1x_2xs_16bpp(void) { DIRTY0(1,2,1,16,) }
  980. void blitscreen_dirty0_vesa_2x_1x_16bpp(void)  { DIRTY0(2,1,0,16,) }
  981. void blitscreen_dirty0_vesa_2x_2x_16bpp(void)  { DIRTY0(2,2,0,16,) }
  982. void blitscreen_dirty0_vesa_2x_2xs_16bpp(void) { DIRTY0(2,2,1,16,) }
  983. void blitscreen_dirty0_vesa_3x_1x_16bpp(void)  { DIRTY0(3,1,0,16,) }
  984. void blitscreen_dirty0_vesa_3x_2x_16bpp(void)  { DIRTY0(3,2,0,16,) }
  985. void blitscreen_dirty0_vesa_3x_2xs_16bpp(void) { DIRTY0(3,2,1,16,) }
  986. void blitscreen_dirty0_vesa_4x_2x_16bpp(void)  { DIRTY0(4,2,0,16,) }
  987. void blitscreen_dirty0_vesa_4x_2xs_16bpp(void) { DIRTY0(4,2,1,16,) }
  988.  
  989. void blitscreen_dirty0_vesa_1x_1x_16bpp_palettized(void)  { DIRTY0(1,1,0,16,_palettized) }
  990. void blitscreen_dirty0_vesa_1x_2x_16bpp_palettized(void)  { DIRTY0(1,2,0,16,_palettized) }
  991. void blitscreen_dirty0_vesa_1x_2xs_16bpp_palettized(void) { DIRTY0(1,2,1,16,_palettized) }
  992. void blitscreen_dirty0_vesa_2x_1x_16bpp_palettized(void)  { DIRTY0(2,1,0,16,_palettized) }
  993. void blitscreen_dirty0_vesa_2x_2x_16bpp_palettized(void)  { DIRTY0(2,2,0,16,_palettized) }
  994. void blitscreen_dirty0_vesa_2x_2xs_16bpp_palettized(void) { DIRTY0(2,2,1,16,_palettized) }
  995. void blitscreen_dirty0_vesa_3x_1x_16bpp_palettized(void)  { DIRTY0(3,1,0,16,_palettized) }
  996. void blitscreen_dirty0_vesa_3x_2x_16bpp_palettized(void)  { DIRTY0(3,2,0,16,_palettized) }
  997. void blitscreen_dirty0_vesa_3x_2xs_16bpp_palettized(void) { DIRTY0(3,2,1,16,_palettized) }
  998. void blitscreen_dirty0_vesa_4x_2x_16bpp_palettized(void)  { DIRTY0(4,2,0,16,_palettized) }
  999. void blitscreen_dirty0_vesa_4x_2xs_16bpp_palettized(void) { DIRTY0(4,2,1,16,_palettized) }
  1000.